home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / javax / swing / JMenuItem.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  20.9 KB  |  667 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)JMenuItem.java    1.69 98/08/28
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14. package javax.swing;
  15.  
  16. import java.util.EventListener;
  17. import java.awt.*;
  18. import java.awt.event.*;
  19. import java.awt.image.*;
  20.  
  21. import java.io.Serializable;
  22. import java.io.ObjectOutputStream;
  23. import java.io.ObjectInputStream;
  24. import java.io.IOException;
  25.  
  26. import javax.swing.plaf.*;
  27. import javax.swing.plaf.basic.*;
  28. import javax.swing.event.*;
  29. import javax.accessibility.*;
  30.  
  31. /**
  32.  * An implementation of a MenuItem. A menu item is essentially a button
  33.  * sitting in a list. When the user selects the "button", the action
  34.  * associated with the menu item is performed. A JMenuItem contained
  35.  * in a JPopupMenu performs exactly that function.
  36.  * <p>
  37.  * For the keyboard keys used by this component in the standard Look and
  38.  * Feel (L&F) renditions, see the
  39.  * <a href="doc-files/Key-Index.html#JMenuItem">JMenuItem</a> key assignments.
  40.  * <p>
  41.  * <strong>Warning:</strong>
  42.  * Serialized objects of this class will not be compatible with 
  43.  * future Swing releases.  The current serialization support is appropriate
  44.  * for short term storage or RMI between applications running the same
  45.  * version of Swing.  A future release of Swing will provide support for
  46.  * long term persistence.
  47.  *
  48.  * @version 1.69 08/28/98
  49.  * @author Georges Saab
  50.  * @author David Karlton
  51.  * @see JPopupMenu
  52.  * @see JMenu
  53.  * @see JCheckBoxMenuItem
  54.  * @see JRadioButtonMenuItem
  55.  */
  56. public class JMenuItem extends AbstractButton implements Accessible,MenuElement  {
  57.  
  58.     /**
  59.      * @see #getUIClassID
  60.      * @see #readObject
  61.      */
  62.     private static final String uiClassID = "MenuItemUI";
  63.  
  64.     /**
  65.      * Creates a menuItem with no set text or icon.
  66.      */
  67.     public JMenuItem() {
  68.         this(null, (Icon)null);
  69.         setRequestFocusEnabled(false);
  70.     }
  71.  
  72.     /**
  73.      * Creates a menuItem with an icon.
  74.      *
  75.      * @param icon the icon of the MenuItem.
  76.      */
  77.     public JMenuItem(Icon icon) {
  78.         this(null, icon);
  79.         setRequestFocusEnabled(false);
  80.     }
  81.  
  82.     /**
  83.      * Creates a menuItem with text.
  84.      *
  85.      * @param text the text of the MenuItem.
  86.      */
  87.     public JMenuItem(String text) {
  88.         this(text, (Icon)null);
  89.     }
  90.     
  91.     /**
  92.      * Creates a menuItem with the supplied text and icon.
  93.      *
  94.      * @param text the text of the MenuItem.
  95.      * @param icon the icon of the MenuItem.
  96.      */
  97.     public JMenuItem(String text, Icon icon) {
  98.         setModel(new DefaultButtonModel());
  99.         init(text, icon);
  100.         setBorderPainted(false);
  101.         setFocusPainted(false);
  102.         setHorizontalTextPosition(JButton.RIGHT);
  103.         setHorizontalAlignment(JButton.LEFT);
  104.         updateUI();
  105.     }
  106.  
  107.     /**
  108.      * Creates a menuItem with the specified text and
  109.      * keyboard mnemonic.
  110.      *
  111.      * @param text the text of the MenuItem.
  112.      * @param mnemonic the keyboard mnemonic for the MenuItem
  113.      */
  114.     public JMenuItem(String text, int mnemonic) {
  115.         setModel(new DefaultButtonModel());
  116.         init(text, null);
  117.         setBorderPainted(false);
  118.         setFocusPainted(false);
  119.         setHorizontalTextPosition(JButton.LEFT);
  120.         setHorizontalAlignment(JButton.LEFT);
  121.         setMnemonic(mnemonic);
  122.         updateUI();
  123.     }
  124.  
  125.     /**
  126.      * Initialize the menu item with the specified text and icon.
  127.      *
  128.      * @param text the text of the MenuItem.
  129.      * @param icon the icon of the MenuItem.
  130.      */
  131.     protected void init(String text, Icon icon) {
  132.         if(text != null) {
  133.             setText(text);
  134.         }
  135.         
  136.         if(icon != null) {
  137.             setIcon(icon);
  138.         }
  139.         
  140.         // Listen for Focus events
  141.         addFocusListener(new MenuItemFocusListener());
  142.     }
  143.  
  144.     private static class MenuItemFocusListener implements FocusListener,
  145.         Serializable {
  146.         public void focusGained(FocusEvent event) {}
  147.         public void focusLost(FocusEvent event) {
  148.             // When focus is lost, repaint if 
  149.             // the focus information is painted
  150.             JMenuItem mi = (JMenuItem)event.getSource();
  151.             if(mi.isFocusPainted()) {
  152.                 mi.repaint();
  153.             }
  154.         }
  155.     }
  156.         
  157.     
  158.     /**
  159.      * Sets the L&F object that renders this component.
  160.      *
  161.      * @param ui  the MenuItemUI L&F object
  162.      * @see UIDefaults#getUI
  163.      * @beaninfo
  164.      * description: The menu item's UI delegate
  165.      *       bound: true
  166.      *      expert: true
  167.      *      hidden: true
  168.      */
  169.     public void setUI(MenuItemUI ui) {
  170.         super.setUI(ui);
  171.     }
  172.     
  173.     /**
  174.      * Notification from the UIFactory that the L&F has changed. 
  175.      * Called to replace the UI with the latest version from the 
  176.      * UIFactory.
  177.      *
  178.      * @see JComponent#updateUI
  179.      */
  180.     public void updateUI() {
  181.         setUI((MenuItemUI)UIManager.getUI(this));
  182.     }
  183.  
  184.  
  185.     /**
  186.      * Returns the name of the L&F class that renders this component.
  187.      *
  188.      * @return "MenuItemUI"
  189.      * @see JComponent#getUIClassID
  190.      * @see UIDefaults#getUI
  191.      */
  192.     public String getUIClassID() {
  193.         return uiClassID;
  194.     }
  195.  
  196.  
  197.     /**
  198.      * Identifies the menu item as "armed". If the mouse button is
  199.      * released while it is over this item, the menu's action event
  200.      * will fire. If the mouse button is released elsewhere, the
  201.      * event will not fire and the menu item will be disarmed.
  202.      * 
  203.      * @param b true to arm the menu item so it can be selected
  204.      * @beaninfo
  205.      *    description: Mouse release will fire an action event
  206.      *         hidden: true
  207.      */
  208.     public void setArmed(boolean b) {
  209.         ButtonModel model = (ButtonModel) getModel();
  210.  
  211.         boolean oldValue = model.isArmed();
  212.         if ((accessibleContext != null) && (oldValue != b)) {
  213.             if (b) {
  214.                 accessibleContext.firePropertyChange(
  215.                         AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  216.                         null, 
  217.                         AccessibleState.ARMED);
  218.             } else {
  219.                 accessibleContext.firePropertyChange(
  220.                         AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
  221.                         AccessibleState.ARMED, 
  222.                         null);
  223.             }
  224.         }
  225.         if(model.isArmed() != b) {
  226.             model.setArmed(b);
  227.         }
  228.     }
  229.  
  230.     /**
  231.      * Returns whether the menu item is "armed".
  232.      * 
  233.      * @return true if the menu item is armed, and it can be selected
  234.      * @see #setArmed
  235.      */
  236.     public boolean isArmed() {
  237.         ButtonModel model = (ButtonModel) getModel();
  238.         return model.isArmed();
  239.     }
  240.  
  241.     /**
  242.      * Enable or disable the menu item.
  243.      *
  244.      * @param b  true to enable the item
  245.      * @beaninfo
  246.      *    description: Does the component react to user interaction
  247.      *          bound: true
  248.      *      preferred: true
  249.      */
  250.     public void setEnabled(boolean b) {
  251.         // Make sure we aren't armed!
  252.         if (b == false)
  253.             setArmed(false);
  254.         super.setEnabled(b);
  255.     }
  256.  
  257.  
  258.     /**
  259.      * Always return true since Menus, by definition, 
  260.      * should always be on top of all other windows.
  261.      */
  262.     // package private
  263.     boolean alwaysOnTop() {
  264.     return true;
  265.     }
  266.  
  267.  
  268.     /* The keystroke which acts as the menu item's accelerator
  269.      */
  270.     private KeyStroke accelerator;
  271.  
  272.     /**
  273.      * Set the key combination which invokes the Menu Item's
  274.      * action listeners without navigating the menu hierarchy.
  275.      *
  276.      * @param keyStroke the KeyStroke which will serve as an accelerator
  277.      * @beaninfo
  278.      *     description: The keystroke combination which will invoke the JMenuItem's
  279.      *                  actionlisteners without navigating the menu hierarchy
  280.      *           bound: true
  281.      *       preferred: true
  282.      */
  283.     public void setAccelerator(KeyStroke keyStroke) {
  284.         if (accelerator != null)
  285.             unregisterKeyboardAction(accelerator);
  286.  
  287.         // PENDING(ges) change this to a (lighter) ActionListener which implements
  288.         // Serializable
  289.     if (keyStroke != null) {
  290.         registerKeyboardAction(new AbstractAction(){
  291.         public void actionPerformed(ActionEvent e) {
  292.             MenuSelectionManager.defaultManager().clearSelectedPath();
  293.             doClick();
  294.         }
  295.         } , keyStroke, WHEN_IN_FOCUSED_WINDOW);
  296.     }
  297.         this.accelerator = keyStroke;
  298.     }
  299.  
  300.     /**
  301.      * Returns the KeyStroke which serves as an accelerator 
  302.      * for the menu item.
  303.      * @return a KeyStroke object identifying the accelerator key
  304.      */
  305.     public KeyStroke getAccelerator() {
  306.         return this.accelerator;
  307.     }
  308.  
  309.     /**
  310.      * Process a mouse event forwarded from the MenuSelectionManager.
  311.      * @param event          A MouseEvent with source being the receiving component.
  312.      * @param componentPath  The MenuElement path array to the receiving component.
  313.      * @param manager        The MenuSelectionManager for the menu hierarchy.
  314.      * This method should process the MouseEvent and change the menu selection if necessary
  315.      * by using MenuSelectionManager's API.
  316.      * <p>
  317.      * Note: you do not have to forward the event to sub-components. This is done automatically
  318.      * by the MenuSelectionManager
  319.      */
  320.     public void processMouseEvent(MouseEvent e,MenuElement path[],MenuSelectionManager manager) {
  321.     processMenuDragMouseEvent(
  322.          new MenuDragMouseEvent(e.getComponent(), e.getID(),
  323.                     e.getWhen(),
  324.                     e.getModifiers(), e.getX(), e.getY(),
  325.                     e.getClickCount(), e.isPopupTrigger(),
  326.                     path, manager));
  327.     }
  328.  
  329.  
  330.     /**
  331.      * Process a key event forwarded from the MenuSelectionManager.
  332.      * @param event          A KeyEvent with source being the receiving component.
  333.      * @param componentPath  The MenuElement path array to the receiving component.
  334.      * @param manager        The MenuSelectionManager for the menu hierarchy.
  335.      * This method should process the KeyEvent and change the menu selection if necessary
  336.      * by using MenuSelectionManager's API.
  337.      * <p>
  338.      * Note: you do not have to forward the event to sub-components. This is done automatically
  339.      * by the MenuSelectionManager
  340.      */
  341.     public void processKeyEvent(KeyEvent e,MenuElement path[],MenuSelectionManager manager) {
  342.     processMenuKeyEvent(new MenuKeyEvent(e.getComponent(), e.getID(),
  343.                          e.getWhen(), e.getModifiers(),
  344.                          e.getKeyCode(), e.getKeyChar(),
  345.                          path, manager));    
  346.     }
  347.  
  348.  
  349.  
  350.     /**
  351.      * Handle mouse drag in a menu.
  352.      *
  353.      * @param e  a MenuDragMouseEvent object
  354.      */
  355.     public void processMenuDragMouseEvent(MenuDragMouseEvent e) {
  356.     switch (e.getID()) {
  357.     case MouseEvent.MOUSE_ENTERED:
  358.         fireMenuDragMouseEntered(e); break;
  359.     case MouseEvent.MOUSE_EXITED:
  360.         fireMenuDragMouseExited(e); break;
  361.     case MouseEvent.MOUSE_DRAGGED:
  362.         fireMenuDragMouseDragged(e); break;
  363.     case MouseEvent.MOUSE_RELEASED:
  364.         fireMenuDragMouseReleased(e); break;
  365.     default: 
  366.         break;
  367.     }
  368.     }
  369.  
  370.     /**
  371.      * Hanlde a keystroke in a menu.
  372.      *
  373.      * @param e  a MenuKeyEvent object
  374.      */
  375.     public void processMenuKeyEvent(MenuKeyEvent e) {
  376.     switch (e.getID()) {
  377.     case KeyEvent.KEY_PRESSED:
  378.         fireMenuKeyPressed(e); break;
  379.     case KeyEvent.KEY_RELEASED:
  380.         fireMenuKeyReleased(e); break;
  381.     case KeyEvent.KEY_TYPED:
  382.         fireMenuKeyTyped(e); break;
  383.     default: 
  384.         break;
  385.     }
  386.     }
  387.  
  388.     /*
  389.      * Notify all listeners that have registered interest for
  390.      * notification on this event type. 
  391.      * @see EventListenerList
  392.      */
  393.     protected void fireMenuDragMouseEntered(MenuDragMouseEvent event) {
  394.         // Guaranteed to return a non-null array
  395.         Object[] listeners = listenerList.getListenerList();
  396.         // Process the listeners last to first, notifying
  397.         // those that are interested in this event
  398.         for (int i = listeners.length-2; i>=0; i-=2) {
  399.             if (listeners[i]==MenuDragMouseListener.class) {
  400.                 // Lazily create the event:
  401.                 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseEntered(event);
  402.             }          
  403.         }
  404.     }   
  405.  
  406.     /*
  407.      * Notify all listeners that have registered interest for
  408.      * notification on this event type.  
  409.      * @see EventListenerList
  410.      */
  411.     protected void fireMenuDragMouseExited(MenuDragMouseEvent event) {
  412.         // Guaranteed to return a non-null array
  413.         Object[] listeners = listenerList.getListenerList();
  414.         // Process the listeners last to first, notifying
  415.         // those that are interested in this event
  416.         for (int i = listeners.length-2; i>=0; i-=2) {
  417.             if (listeners[i]==MenuDragMouseListener.class) {
  418.                 // Lazily create the event:
  419.                 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseExited(event);
  420.             }          
  421.         }
  422.     }   
  423.  
  424.     /*
  425.      * Notify all listeners that have registered interest for
  426.      * notification on this event type.
  427.      * @see EventListenerList
  428.      */
  429.     protected void fireMenuDragMouseDragged(MenuDragMouseEvent event) {
  430.         // Guaranteed to return a non-null array
  431.         Object[] listeners = listenerList.getListenerList();
  432.         // Process the listeners last to first, notifying
  433.         // those that are interested in this event
  434.         for (int i = listeners.length-2; i>=0; i-=2) {
  435.             if (listeners[i]==MenuDragMouseListener.class) {
  436.                 // Lazily create the event:
  437.                 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseDragged(event);
  438.             }          
  439.         }
  440.     }   
  441.  
  442.     /*
  443.      * Notify all listeners that have registered interest for
  444.      * notification on this event type. 
  445.      * @see EventListenerList
  446.      */
  447.     protected void fireMenuDragMouseReleased(MenuDragMouseEvent event) {
  448.         // Guaranteed to return a non-null array
  449.         Object[] listeners = listenerList.getListenerList();
  450.         // Process the listeners last to first, notifying
  451.         // those that are interested in this event
  452.         for (int i = listeners.length-2; i>=0; i-=2) {
  453.             if (listeners[i]==MenuDragMouseListener.class) {
  454.                 // Lazily create the event:
  455.                 ((MenuDragMouseListener)listeners[i+1]).menuDragMouseReleased(event);
  456.             }          
  457.         }
  458.     }   
  459.  
  460.     /*
  461.      * Notify all listeners that have registered interest for
  462.      * notification on this event type. 
  463.      * @see EventListenerList
  464.      */
  465.     protected void fireMenuKeyPressed(MenuKeyEvent event) {
  466.         // Guaranteed to return a non-null array
  467.         Object[] listeners = listenerList.getListenerList();
  468.         // Process the listeners last to first, notifying
  469.         // those that are interested in this event
  470.         for (int i = listeners.length-2; i>=0; i-=2) {
  471.             if (listeners[i]==MenuKeyListener.class) {
  472.                 // Lazily create the event:
  473.                 ((MenuKeyListener)listeners[i+1]).menuKeyPressed(event);
  474.             }          
  475.         }
  476.     }   
  477.  
  478.     /*
  479.      * Notify all listeners that have registered interest for
  480.      * notification on this event type. 
  481.      * @see EventListenerList
  482.      */
  483.     protected void fireMenuKeyReleased(MenuKeyEvent event) {
  484.         // Guaranteed to return a non-null array
  485.         Object[] listeners = listenerList.getListenerList();
  486.         // Process the listeners last to first, notifying
  487.         // those that are interested in this event
  488.         for (int i = listeners.length-2; i>=0; i-=2) {
  489.             if (listeners[i]==MenuKeyListener.class) {
  490.                 // Lazily create the event:
  491.                 ((MenuKeyListener)listeners[i+1]).menuKeyReleased(event);
  492.             }          
  493.         }
  494.     }   
  495.  
  496.     /*
  497.      * Notify all listeners that have registered interest for
  498.      * notification on this event type. 
  499.      * @see EventListenerList
  500.      */
  501.     protected void fireMenuKeyTyped(MenuKeyEvent event) {
  502.         // Guaranteed to return a non-null array
  503.         Object[] listeners = listenerList.getListenerList();
  504.         // Process the listeners last to first, notifying
  505.         // those that are interested in this event
  506.         for (int i = listeners.length-2; i>=0; i-=2) {
  507.             if (listeners[i]==MenuKeyListener.class) {
  508.                 // Lazily create the event:
  509.                 ((MenuKeyListener)listeners[i+1]).menuKeyTyped(event);
  510.             }          
  511.         }
  512.     }   
  513.  
  514.     /**
  515.      * Called by the MenuSelectionManager when the MenuElement is selected
  516.      * or unselected.
  517.      * 
  518.      * @param isIncluded  true if this menu item is on the part of the menu
  519.      *                    path that changed, false if this menu is part of the
  520.      *                    a menu path that changed, but this particular part of
  521.      *                    that path is still the same
  522.      * @see MenuSelectionManager#setSelectedPath(MenuElement[])
  523.      */
  524.     public void menuSelectionChanged(boolean isIncluded) {
  525.         setArmed(isIncluded);
  526.     }
  527.  
  528.     /**
  529.      * This method returns an array containing the sub-menu components for this menu component.
  530.      *
  531.      * @return an array of MenuElements
  532.      */
  533.     public MenuElement[] getSubElements() {
  534.         return new MenuElement[0];
  535.     }
  536.     
  537.     /**
  538.      * This method returns the java.awt.Component used to paint this object.
  539.      * The returned component will be used to convert events and detect if an event is inside
  540.      * a menu component.
  541.      *
  542.      * @return the Component that paints this menu item
  543.      */
  544.     public Component getComponent() {
  545.         return this;
  546.     }
  547.  
  548.     /**
  549.      * Adds a MenuDragMouseListener to the menu item
  550.      */
  551.     public void addMenuDragMouseListener(MenuDragMouseListener l) {
  552.         listenerList.add(MenuDragMouseListener.class, l);
  553.     }
  554.  
  555.     /**
  556.      * Removes a MenuDragMouseListener from the menu item
  557.      */
  558.     public void removeMenuDragMouseListener(MenuDragMouseListener l) {
  559.         listenerList.remove(MenuDragMouseListener.class, l);
  560.     }
  561.  
  562.     /**
  563.      * Adds a MenuKeyListener to the menu item
  564.      */
  565.     public void addMenuKeyListener(MenuKeyListener l) {
  566.         listenerList.add(MenuKeyListener.class, l);
  567.     }
  568.  
  569.     /**
  570.      * Removes a MenuKeyListener from the menu item
  571.      */
  572.     public void removeMenuKeyListener(MenuKeyListener l) {
  573.         listenerList.remove(MenuKeyListener.class, l);
  574.     }
  575.  
  576.     /**
  577.      * See JComponent.readObject() for information about serialization
  578.      * in Swing.
  579.      */
  580.     private void readObject(ObjectInputStream s) 
  581.     throws IOException, ClassNotFoundException 
  582.     {
  583.         s.defaultReadObject();
  584.     if (getUIClassID().equals(uiClassID)) {
  585.         updateUI();
  586.     }
  587.     }
  588.  
  589.     private void writeObject(ObjectOutputStream s) throws IOException {
  590.         s.defaultWriteObject();
  591.     if ((ui != null) && (getUIClassID().equals(uiClassID))) {
  592.         ui.installUI(this);
  593.     }
  594.     }
  595.  
  596.  
  597.     /**
  598.      * Returns a string representation of this JMenuItem. This method 
  599.      * is intended to be used only for debugging purposes, and the 
  600.      * content and format of the returned string may vary between      
  601.      * implementations. The returned string may be empty but may not 
  602.      * be <code>null</code>.
  603.      * <P>
  604.      * Overriding paramString() to provide information about the
  605.      * specific new aspects of the JFC components.
  606.      * 
  607.      * @return  a string representation of this JMenuItem.
  608.      */
  609.     protected String paramString() {
  610.     return super.paramString();
  611.     }
  612.  
  613. /////////////////
  614. // Accessibility support
  615. ////////////////
  616.  
  617.     /**
  618.      * Get the AccessibleContext associated with this JComponent
  619.      *
  620.      * @return the AccessibleContext of this JComponent
  621.      */
  622.     public AccessibleContext getAccessibleContext() {
  623.         if (accessibleContext == null) {
  624.             accessibleContext = new AccessibleJMenuItem();
  625.         }
  626.         return accessibleContext;
  627.     }
  628.  
  629.  
  630.     /**
  631.      * The class used to obtain the accessible role for this object.
  632.      * <p>
  633.      * <strong>Warning:</strong>
  634.      * Serialized objects of this class will not be compatible with
  635.      * future Swing releases.  The current serialization support is appropriate
  636.      * for short term storage or RMI between applications running the same
  637.      * version of Swing.  A future release of Swing will provide support for
  638.      * long term persistence.
  639.      */
  640.     protected class AccessibleJMenuItem extends AccessibleAbstractButton implements ChangeListener {
  641.  
  642.         AccessibleJMenuItem() {
  643.             super();
  644.             JMenuItem.this.addChangeListener(this);
  645.         }
  646.  
  647.         /**
  648.          * Get the role of this object.
  649.          *
  650.          * @return an instance of AccessibleRole describing the role of the 
  651.          * object
  652.          */
  653.         public AccessibleRole getAccessibleRole() {
  654.             return AccessibleRole.MENU_ITEM;
  655.         }
  656.  
  657.         /**
  658.          * Supports the change listener interface and fires property change
  659.          */
  660.         public void stateChanged(ChangeEvent e) {
  661.             firePropertyChange(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY, 
  662.                                new Boolean(false), new Boolean(true));
  663.         }
  664.     } // inner class AccessibleJMenuItem
  665. }
  666.  
  667.